package cn.chinaunicom.sdsi.frm.workflow.task.dao.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.history.NativeHistoricTaskInstanceQuery;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import cn.chinaunicom.sdsi.frm.workflow.bean.TaskVO;
import cn.chinaunicom.sdsi.frm.workflow.common.UtilDateTime;
import cn.chinaunicom.sdsi.frm.workflow.task.dao.ActTaskHistDao;

/**
 * 任务模块数据访问层组件-原生查询方式
 * 
 * @author liyh
 */
@Repository("actTaskHistNativeDao")
public class ActTaskHistNativeDaoImpl implements ActTaskHistDao {

	private static final Log log = LogFactory.getLog(ActTaskHistNativeDaoImpl.class);

	/**
	 * activiti历史信息查询组件
	 */
	private HistoryService historyService;
	/**
	 * 流程引擎相关信息服务组件
	 */
	private ManagementService managementService;
	/**
	 * Spring提供的JDBC工具
	 */
	private JdbcTemplate jdbcTemplate;

	/**
	 * 根据查询条件分页查询版本最新的流程定义
	 * 
	 * @param vo
	 *            查询实体
	 * @param firstResult
	 *            第一条记录位置
	 * @param maxResults
	 *            每页记录数
	 * @return 返回结果集
	 */
	@Override
	public List<HistoricTaskInstance> listHasDone4Page(TaskVO vo, int firstResult, int maxResults) {

		// 赋值任务表名及变量表名
		String taskName = managementService.getTableName(HistoricTaskInstance.class);
		StringBuilder sb = new StringBuilder("SELECT DISTINCT RES.* FROM ").append(taskName).append(" RES");

		NativeHistoricTaskInstanceQuery nhtiq = historyService.createNativeHistoricTaskInstanceQuery();

		makeCondition(nhtiq, vo, sb, false);
		log.debug("search Task use DAO, add condition done");

		return nhtiq.listPage(firstResult, maxResults);
	}

	/**
	 * 据传入参数查询符合条件的记录条数
	 * 
	 * @param vo
	 *            任务封装条件
	 * @return 符合条件记录数
	 */
	@Override
	public long listFilteredCount(TaskVO vo) {
		// 赋值任务表名及变量表名
		String taskName = managementService.getTableName(HistoricTaskInstance.class);
		StringBuilder sb = new StringBuilder("SELECT COUNT(RES.ID_) FROM ").append(taskName).append(" RES");

		NativeHistoricTaskInstanceQuery nhtiq = historyService.createNativeHistoricTaskInstanceQuery();

		makeCondition(nhtiq, vo, sb, true);
		log.debug("search Task use DAO, get FilteredCount ");

		return nhtiq.count();
	}

	/**
	 * 据查询条件查询全部记录的条数
	 * 
	 * @param vo
	 *            查询实体
	 * @return 全部记录数
	 */
	@Override
	public long listTotalCount(TaskVO vo) {
		String tableName = managementService.getTableName(HistoricTaskInstance.class);
		String[] userIds = vo.getAssigneeIds();

		StringBuilder sb = new StringBuilder("SELECT COUNT(RES.ID_) FROM ").append(tableName).append(" RES WHERE (")
				.append(parseUserIds(userIds)).append(") AND RES.END_TIME_ IS NOT NULL");

		NativeHistoricTaskInstanceQuery nhtiq = historyService.createNativeHistoricTaskInstanceQuery();
		log.debug("search Task use DAO, get TotalCount ");

		return nhtiq.sql(sb.toString()).count();
	}

	/**
	 * 复用拼装查询条件
	 * 
	 * @param query
	 *            查询体
	 * @param vo
	 *            封装条件
	 * @param sb
	 *            拼装语句
	 * @param count
	 *            是否条数查询
	 * @return
	 */
	private NativeHistoricTaskInstanceQuery makeCondition(NativeHistoricTaskInstanceQuery query, TaskVO vo,
			StringBuilder sb, boolean count) {

		String tableName = managementService.getTableName(HistoricVariableInstance.class);
		/*
		 * 获取全部参数
		 */
		String[] userIds = vo.getAssigneeIds();
		String title = vo.getTitle();
		String linkName = vo.getLinkName();
		Date completeTimeStart = StringUtils.isBlank(vo.getCompleteTimeStart()) ? null
				: UtilDateTime.str2Date(vo.getCompleteTimeStart(), "yyyy-MM-dd");
		Date completeTimeEnd = StringUtils.isBlank(vo.getCompleteTimeEnd()) ? null
				: UtilDateTime.str2Date(vo.getCompleteTimeEnd(), "yyyy-MM-dd");

		// 标题作为表连接
		if (!StringUtils.isBlank(title)) {
			sb.append(" INNER JOIN ").append(tableName).append(" A0 ON RES.PROC_INST_ID_ = A0.PROC_INST_ID_");
		}

		// 查询本人待办任务数量且实例状态有效
		sb.append(" WHERE (").append(parseUserIds(userIds)).append(") AND RES.END_TIME_ IS NOT NULL");
		// 环节名称作为查询条件
		if (!StringUtils.isBlank(linkName)) {
			sb.append(" AND RES.NAME_ LIKE #{linkName}");
		}
		// 依据任务的完成时间查询-开始区间-1-筛选条件
		if (completeTimeStart != null) {
			sb.append(" AND RES.END_TIME_ > #{completeTimeStart}");
		}
		// 依据任务的创建时间查询-结束区间-1-筛选条件
		if (completeTimeEnd != null) {
			sb.append(" AND RES.END_TIME_ <= #{completeTimeEnd}");
		}

		// 依据流程标题查询-2-筛选条件
		if (!StringUtils.isBlank(title)) {
			sb.append(" AND A0.TASK_ID_ IS NULL AND A0.NAME_ = 'title' AND A0.VAR_TYPE_ = 'string'")
					.append(" AND A0.TEXT_ LIKE #{title}");
		}

		// 仅针对查询结果加入排序
		if (!count) {
			sb.append(" ORDER BY RES.END_TIME_ DESC");
		}
		query.sql(sb.toString());

		// 环节名称作为筛选条件填入参数
		if (!StringUtils.isBlank(linkName)) {
			query.parameter("linkName", "%" + linkName + "%");
		}
		// 依据任务的创建时间查询-开始区间-2-传入参数
		if (completeTimeStart != null) {
			query.parameter("completeTimeStart", completeTimeStart);
		}
		// 依据任务的创建时间查询-结束区间-2-传入参数
		if (completeTimeEnd != null) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(completeTimeEnd);
			calendar.add(Calendar.DATE, 1);

			query.parameter("completeTimeEnd", calendar.getTime());
		}

		// 标题作为筛选条件填入参数
		if (!StringUtils.isBlank(title)) {
			query.parameter("title", "%" + title + "%");
		}

		return query;
	}

	/**
	 * 将用户岗位字符串数组转化为用户筛选条件
	 * 
	 * @param strs
	 *            岗位字符串数组
	 * @return 筛选条件
	 */
	private String parseUserIds(String[] strs) {

		StringBuilder sb = new StringBuilder("");

		for (int i = 0; i < strs.length; i++) {

			if (i == strs.length - 1) {
				sb.append("RES.ASSIGNEE_ = '").append(strs[i]).append("'");
			} else {
				sb.append("RES.ASSIGNEE_ = '").append(strs[i]).append("' OR ");
			}
		}

		return sb.toString();
	}

	/**
	 * 据参数名返回参数值
	 * 
	 * @param task
	 *            历史任务
	 * @param varName
	 *            变量名称
	 * @return 索取变量值
	 */
	@Override
	public Object parseVariable(HistoricTaskInstance task, String varName) {
		String tableName = managementService.getTableName(HistoricVariableInstance.class);
		// 获取实例ID
		String processInstanceId = task.getProcessInstanceId();

		StringBuilder sb = new StringBuilder("SELECT VAR.* FROM ");
		sb.append(tableName).append(" VAR WHERE VAR.PROC_INST_ID_ = '").append(processInstanceId)
				.append("' AND VAR.TASK_ID_ IS NULL AND VAR.NAME_ = '").append(varName).append("'");

		log.debug("search task vars: " + varName);
		List<Map<String, Object>> list = jdbcTemplate.queryForList(sb.toString());

		if (list == null || list.size() == 0) {
			return null;
		}

		return list.get(0).get("TEXT_");
	}

	@Autowired
	public void setHistoryService(HistoryService historyService) {
		this.historyService = historyService;
	}

	@Autowired
	public void setManagementService(ManagementService managementService) {
		this.managementService = managementService;
	}

	@Autowired
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
}
